
#include "./basic.h"

namespace ai_sim {

void convert2NG(int order, int *r) {
    r[0] = floor(order / 8);
    r[1] = order - r[0] * 8;
}

void convert2RL(int order, int side_length, int *r) {
    r[0] = floor(order / side_length);
    r[1] = order - r[0] * side_length;
}

int compute_nvpeer(int src, int dest) {
    if (dest - src == 4 || dest - src == -4) {
        return 0;
    } else if (dest > src && dest - src <= 3) {
        return dest - src;
    } else if (dest < src && src - dest <= 3) {
        return dest + 4 - src;
    } else {
        return -1;
    }
}

int get_rand(int biggest) {
    return rand() % biggest;
}

int compute_awgr_dest(int src, int dest, int side_length) {
    if (abs(src - dest) < side_length) {
        return dest % side_length;
    } else if (abs(dest - src) % side_length == 0) {
        return floor(dest / side_length);
    } else {
        // Connot directly send to a gpu that are not in a row/col
        return - 1;
    }
}

int get_dest_addr(const char *pkt_name) {
    char dest_addr[3];
    for (int i = 0; i < 2; i++) {
        dest_addr[i] = pkt_name[i];
    }
    dest_addr[2]='\0';
    return atoi(dest_addr);
}

int log2(int n) {
    if (n < 0 || ((n & (n - 1)) != 0)) {
        return -1;
    } else if (n == 1) {
        return 0;
    } else {
        return 1+log2(n>>1);
    }
}

int getOutPortTo(omnetpp::cModule* src, omnetpp::cModule* dest) {
    for (omnetpp::cModule::GateIterator i(dest); !i.end(); i++) {
        omnetpp::cGate *gate = *i;
        if (gate->getType() == omnetpp::cGate::OUTPUT) continue;
        omnetpp::cGate* tmp_src_gate =
            gate->getIncomingTransmissionChannel()->getSourceGate();
        if (tmp_src_gate->getOwnerModule() == src) return tmp_src_gate->getId();
        else continue;
    }
    return -1;
}
}  // namespace ai_sim
